use url::Url;
use crate::error::{DownloadError, DownloadResult};

/// URL解析器trait
pub trait UrlResolver: Send + Sync + std::fmt::Debug {
    /// 解析URL，将相对路径转换为绝对路径
    fn resolve_url(&self, base_url: &Url, segment_url: &str) -> DownloadResult<String>;
    
    /// 检查URL是否为绝对路径
    fn is_absolute(&self, url: &str) -> bool;
    
    /// 获取解析器类型描述
    fn resolver_type(&self) -> &'static str;
}

/// 智能URL解析器（自动检测绝对和相对路径）
#[derive(Debug, Clone)]
pub struct SmartUrlResolver;

impl UrlResolver for SmartUrlResolver {
    fn resolve_url(&self, base_url: &Url, segment_url: &str) -> DownloadResult<String> {
        if self.is_absolute(segment_url) {
            // 已经是绝对路径，直接返回
            Ok(segment_url.to_string())
        } else {
            // 相对路径，需要与base_url组合
            let resolved = base_url.join(segment_url)?;
            Ok(resolved.to_string())
        }
    }
    
    fn is_absolute(&self, url: &str) -> bool {
        url.starts_with("http://") || url.starts_with("https://") || url.starts_with("ftp://")
    }
    
    fn resolver_type(&self) -> &'static str {
        "smart"
    }
}

/// 绝对路径解析器（假设所有URL都是绝对路径）
#[derive(Debug, Clone)]
pub struct AbsoluteUrlResolver;

impl UrlResolver for AbsoluteUrlResolver {
    fn resolve_url(&self, _base_url: &Url, segment_url: &str) -> DownloadResult<String> {
        if self.is_absolute(segment_url) {
            Ok(segment_url.to_string())
        } else {
            Err(DownloadError::Url(format!("期望绝对路径，但得到相对路径: {segment_url}")))
        }
    }
    
    fn is_absolute(&self, url: &str) -> bool {
        url.starts_with("http://") || url.starts_with("https://") || url.starts_with("ftp://")
    }
    
    fn resolver_type(&self) -> &'static str {
        "absolute"
    }
}

/// 相对路径解析器（假设所有URL都是相对路径）
#[derive(Debug, Clone)]
pub struct RelativeUrlResolver;

impl UrlResolver for RelativeUrlResolver {
    fn resolve_url(&self, base_url: &Url, segment_url: &str) -> DownloadResult<String> {
        if self.is_absolute(segment_url) {
            // 即使是绝对路径，也按相对路径处理（这种情况比较少见）
            Ok(segment_url.to_string())
        } else {
            let resolved = base_url.join(segment_url)?;
            Ok(resolved.to_string())
        }
    }
    
    fn is_absolute(&self, url: &str) -> bool {
        url.starts_with("http://") || url.starts_with("https://") || url.starts_with("ftp://")
    }
    
    fn resolver_type(&self) -> &'static str {
        "relative"
    }
}

/// URL解析器工厂
pub struct UrlResolverFactory;

impl UrlResolverFactory {
    /// 创建智能URL解析器（推荐使用）
    pub fn create_smart_resolver() -> Box<dyn UrlResolver> {
        Box::new(SmartUrlResolver)
    }
    
    /// 创建绝对路径解析器
    pub fn create_absolute_resolver() -> Box<dyn UrlResolver> {
        Box::new(AbsoluteUrlResolver)
    }
    
    /// 创建相对路径解析器
    pub fn create_relative_resolver() -> Box<dyn UrlResolver> {
        Box::new(RelativeUrlResolver)
    }
    
    /// 根据字符串创建解析器
    pub fn create_resolver(resolver_type: &str) -> DownloadResult<Box<dyn UrlResolver>> {
        match resolver_type.to_lowercase().as_str() {
            "smart" | "auto" => Ok(Self::create_smart_resolver()),
            "absolute" | "abs" => Ok(Self::create_absolute_resolver()),
            "relative" | "rel" => Ok(Self::create_relative_resolver()),
            _ => Err(DownloadError::Config(format!("不支持的URL解析器类型: {resolver_type}"))),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn create_test_base_url() -> Url {
        Url::parse("https://example.com/videos/").unwrap()
    }

    #[test]
    fn test_smart_url_resolver_absolute() {
        let resolver = SmartUrlResolver;
        let base_url = create_test_base_url();
        
        let absolute_url = "https://cdn.example.com/segment001.ts";
        let result = resolver.resolve_url(&base_url, absolute_url).unwrap();
        assert_eq!(result, absolute_url);
        
        assert!(resolver.is_absolute(absolute_url));
    }

    #[test]
    fn test_smart_url_resolver_relative() {
        let resolver = SmartUrlResolver;
        let base_url = create_test_base_url();
        
        let relative_url = "segment001.ts";
        let result = resolver.resolve_url(&base_url, relative_url).unwrap();
        assert_eq!(result, "https://example.com/videos/segment001.ts");
        
        assert!(!resolver.is_absolute(relative_url));
    }

    #[test]
    fn test_smart_url_resolver_relative_with_path() {
        let resolver = SmartUrlResolver;
        let base_url = create_test_base_url();
        
        let relative_url = "../other/segment001.ts";
        let result = resolver.resolve_url(&base_url, relative_url).unwrap();
        assert_eq!(result, "https://example.com/other/segment001.ts");
    }

    #[test]
    fn test_absolute_url_resolver() {
        let resolver = AbsoluteUrlResolver;
        let base_url = create_test_base_url();
        
        // 测试绝对路径
        let absolute_url = "https://cdn.example.com/segment001.ts";
        let result = resolver.resolve_url(&base_url, absolute_url).unwrap();
        assert_eq!(result, absolute_url);
        
        // 测试相对路径应该失败
        let relative_url = "segment001.ts";
        let result = resolver.resolve_url(&base_url, relative_url);
        assert!(result.is_err());
    }

    #[test]
    fn test_relative_url_resolver() {
        let resolver = RelativeUrlResolver;
        let base_url = create_test_base_url();
        
        let relative_url = "segment001.ts";
        let result = resolver.resolve_url(&base_url, relative_url).unwrap();
        assert_eq!(result, "https://example.com/videos/segment001.ts");
    }

    #[test]
    fn test_url_resolver_factory() {
        // 测试智能解析器
        let smart = UrlResolverFactory::create_smart_resolver();
        assert_eq!(smart.resolver_type(), "smart");
        
        // 测试绝对路径解析器
        let absolute = UrlResolverFactory::create_absolute_resolver();
        assert_eq!(absolute.resolver_type(), "absolute");
        
        // 测试相对路径解析器
        let relative = UrlResolverFactory::create_relative_resolver();
        assert_eq!(relative.resolver_type(), "relative");
        
        // 测试字符串创建
        let smart2 = UrlResolverFactory::create_resolver("smart").unwrap();
        assert_eq!(smart2.resolver_type(), "smart");
        
        let auto = UrlResolverFactory::create_resolver("auto").unwrap();
        assert_eq!(auto.resolver_type(), "smart");
        
        // 测试无效类型
        let invalid = UrlResolverFactory::create_resolver("invalid");
        assert!(invalid.is_err());
    }

    #[test]
    fn test_resolver_types() {
        let smart = SmartUrlResolver;
        let absolute = AbsoluteUrlResolver;
        let relative = RelativeUrlResolver;
        
        assert_eq!(smart.resolver_type(), "smart");
        assert_eq!(absolute.resolver_type(), "absolute");
        assert_eq!(relative.resolver_type(), "relative");
    }

    #[test]
    fn test_url_validation() {
        let resolver = SmartUrlResolver;
        
        // 测试各种绝对URL格式
        assert!(resolver.is_absolute("https://example.com/video.ts"));
        assert!(resolver.is_absolute("http://example.com/video.ts"));
        assert!(resolver.is_absolute("ftp://example.com/video.ts"));
        
        // 测试相对URL
        assert!(!resolver.is_absolute("video.ts"));
        assert!(!resolver.is_absolute("../video.ts"));
        assert!(!resolver.is_absolute("/absolute/path/video.ts"));
    }
}